# _*_ coding: utf-8 _*_
from odoo import models, api, fields, _
from odoo.exceptions import UserError


class PurchaseTolerance(models.Model):
    _name = "purchase.tolerance"
    _description = "Purchase Tolerance"

    name = fields.Char(string="Name")
    active = fields.Boolean(default=True, string="Active")
    item_ids = fields.One2many("purchase.tolerance.item", "tolerance_id", string="Lines")

    @api.multi
    def get_tolerance_items(self, product_id):
        self.ensure_one()
        ToleranceItem = self.env["purchase.tolerance.item"]
        product = self.env["product.product"].browse(product_id)
        if not product:
            return ToleranceItem
        items = ToleranceItem.search([
            ("tolerance_id", "=", self.id),
            "|", ("date_end", ">=", fields.Date.today()), ("date_end", "=", False),
            "|", ("date_start", "<=", fields.Date.today()), ("date_start", "=", False),
            "|",
            "&", ("applied_on", "=", "0_product_variant"), ("product_id", "=", product_id),
            "|", "&", ("applied_on", "=", "1_product"), ("product_tmpl_id", "=", product.product_tmpl_id.id),
            "&", ("applied_on", "=", "2_product_category"), ("categ_id", "=", product.categ_id.id),
        ])
        return items


class PurchaseToleranceItem(models.Model):
    _name = "purchase.tolerance.item"
    _description = "Purchase Tolerance Item"

    name = fields.Char(compute="_compute_name", string="Name")
    tolerance_id = fields.Many2one("purchase.tolerance", string="Purchase Tolerance")
    applied_on = fields.Selection([
        ("0_product_variant", "Product Variant"),
        ("1_product", "Product Template"),
        ("2_product_category", "Product Category")
    ], string="Applied On")

    categ_id = fields.Many2one("product.category", string="Product Category", ondelete="restrict")
    product_tmpl_id = fields.Many2one("product.template", string="Product Template", ondelete="restrict")
    product_id = fields.Many2one("product.product", string="Product", ondelete="restrict")
    qty = fields.Float(string="Quantity")

    date_start = fields.Date(string="Start Date")
    date_end = fields.Date(string="Start End")

    over_charge_percentage = fields.Float(string="Over charge Percentage")
    less_charge_percentage = fields.Float(string="Less charge Percentage", default=100.0)

    @api.depends("applied_on", "categ_id", "product_tmpl_id", "product_id")
    def _compute_name(self):
        for item in self:
            if item.applied_on == "0_product_variant":
                item.name = item.product_id.display_name.replace('[%s]' % item.product_id.code, '')
            elif item.applied_on == "1_product":
                item.name = item.product_tmpl_id.name
            elif item.applied_on == "2_product_category":
                item.name = _("Category: %s") % (item.categ_id.name)

    @api.multi
    def check_product_qty(self, purchase_order_product_qty, pack_qty_done, product_name=""):
        sorted_items = self.sorted("qty")
        # fixme 这里或许可以想一个更好的算法，来实现阶梯价的算法
        if sorted_items:
            item = sorted_items[0]
            index = 1
            while index < len(sorted_items):
                if sorted_items[index].qty < pack_qty_done:
                    item = sorted_items[index]
                else:
                    break
                index += 1
            min_qty = purchase_order_product_qty * (1 - item.less_charge_percentage/100.0)
            max_qty = purchase_order_product_qty * (1 + item.over_charge_percentage/100.0)

            if not (min_qty <= pack_qty_done <= max_qty):
                raise UserError(_("Can not receive, out of tolerance control!\nProduct:%s,Min:%f,Max:%f") % (
                    product_name, min_qty, max_qty))
